#include<ModV550.hh>
#include<ModV551.hh>

#include <hbook.hh>

#include<stdio.h>
#include<signal.h>
#include<math.h>
#include<sys/time.h>
#include <iostream>
#include <stdlib.h>


#define NumOfChan 1280
#define NumOfSil 3
#define BuffSize NumOfChan*NumOfSil

#define EventLength 1280*3 + 20 + 256 + 10

//VME ADC Modules V550
#define NumOfADC 2
ModV550* v550[NumOfADC];
bool ADC_Status[4];

#define Base_address_550 0x00860000
#define Step_address_550 0x000A0000

//VME Sequencer V551B
#define Base_address_551 0x00880000
ModV551* v551 = new ModV551(Base_address_551);

//signal
static int sig_int = 1;
static int sig_hup = 1;
void ctrl_c(int);
void hungup(int);

//FLAGS

static int FLAG_DAQ = 1;
static int FLAG_CALIB = 0;

char CharTmp[20];
static int NumRun =1000;
static char NumEvents[20];
static int CalRunNum = 0;


//Function declarations
void DAQMenu();
int Run(int);
int RunDisplay(int);
void CalibExtTrig();
void CalibAutoTrig();
void SetZero();

void WriteCalFile();
void ReadCalFile();

int main(){
 
  /*---------------- VME modules initialisation ----------------*/

  /*** VME Sequencer V551B ***/
  v551->Init(NumOfChan);
  //v551->GetStatus();
  //v551->GetTest();
  
  /*** VME ADC Modules V550 ***/
  for(int i = 0; i < NumOfADC; i++){
    
    v550[i] = new ModV550(Base_address_550 + i*Step_address_550);
    v550[i]->Init(NumOfChan);
    //v550[i]->GetStatus();
    
  }//i
  
  //only 3 sillicon detectors
  ADC_Status[0] = true; //telescope module 1
  ADC_Status[1] = true; //telescope module 2
  ADC_Status[2] = false; //not active ADC in v550
  ADC_Status[3] = true; //telescope module 3

  /*---------------- VME modules initialisation ----------------*/

  /*----------------      signal handling      ----------------*/

  signal(SIGINT,ctrl_c);
  signal(SIGHUP,hungup);

  /*----------------      signal handling      ----------------*/

  /*----------------         DAQ menu          ----------------*/

  DAQMenu();

  /*----------------         DAQ menu          ----------------*/
  
  delete v551; 
  for(int i = 0; i < NumOfADC; i++) delete v550[i];
  
}//main program
/*----------------      signal handling      ----------------*/
void ctrl_c(int){
  sig_int = 0;
  printf("\n CTRL-C pressed \n\r"); 
}//ctrl_c
void hungup(int)
{
  sig_hup = 0;
  printf("\n Signal HUP received \n\r");
}//hungup
/*----------------      signal handling      ----------------*/
void DAQMenu(){
  while(FLAG_DAQ && sig_hup){

    printf("========================================== \n\r");
    printf("=                                        = \n\r");
    printf("=    DAQ for silicon MVD telescope       = \n\r");
    printf("=                                        = \n\r");
    printf("========================================== \n\r");
    printf(" W - Write Calibration file                \n\r");
    printf(" T - Read Calibration file                 \n\r");
    printf(" R - Start Run                             \n\r");
    printf(" D - Start Run in the display mode         \n\r");
    printf(" A - Calibration with the auto trigger     \n\r");
    printf(" E - Calibration with the external trigger \n\r");
    printf(" Z - Set pedestals and thresholds to 0     \n\r");
    printf(" Q - Quit                                  \n\r");
    printf(" > ");

    fgets(CharTmp,20,stdin);
    CharTmp[0] = toupper(CharTmp[0]);

    switch(CharTmp[0]){
    case 'T':
      sig_int = 1;

   	  printf("=========================================================================== \n\n\r");
   	  printf("!!! Calibration File was reading                                            \n\r");
   	  printf("=========================================================================== \n\n\r");

   	  ReadCalFile();
   	  break;

    case 'W':
      sig_int = 1;

   	  printf("=========================================================================== \n\n\r");
   	  printf("!!! Calibration File was write                                            \n\r");
   	  printf("=========================================================================== \n\n\r");

   	  WriteCalFile();
   	  break;

    case 'R':
      sig_int = 1;
      if(!FLAG_CALIB){
    	  printf("=========================================================================== \n\n\r");
    	  printf("!!! Warning: Before taking data you have to make calibration                  \n\r");
    	  printf("!!! Warning: Close the shutter and use calibration in the auto trigger mode   \n\n\r");
    	  printf("=========================================================================== \n\n\r");
    	  break;
      }


      //fgets(CharTmp,20,stdin);
      Run(NumRun);
      NumRun++;
      break;

    case 'D':
      sig_int = 1;
      if(!FLAG_CALIB){
    	  printf("=========================================================================== \n\n\r");
    	  printf("!!! Warning: Before taking data you have to make calibration                  \n\r");
    	  printf("!!! Warning: Close the shutter and use calibration in the auto trigger mode   \n\n\r");
    	  printf("=========================================================================== \n\n\r");
		break;
      }
      printf("DAQ: Set the run number: ");
      fgets(CharTmp,20,stdin);
      RunDisplay(atoi(CharTmp));
      break;

    case 'A':
      CalibAutoTrig();
      break;

    case 'E':
      CalibExtTrig();
      break;

    case 'Z':
      SetZero();
      break;

    case 'Q':
      FLAG_DAQ = 0;
      break;

    default:
      break;

    }//switch

  }//while

}//RunMenu
int Run(int RunNumber){
  v551->Init(NumOfChan);
  for(int i = 0; i < NumOfADC; i++) v550[i]->Init(NumOfChan);
  char OFName[200];

  printf("DAQ: Set number of events: ");
  fgets(NumEvents,20,stdin);

  FILE* fp ;
  //========================
  //
  //========================
  while(1){
	  sprintf(OFName,"./DATA/si_run%d.dat",NumRun);
	  fp = fopen(OFName,"r");
	  if(fp){
		  NumRun++;
		  fclose(fp);
	  }//if
	  else{
		  fp = fopen(OFName,"w");
		  if(fp == NULL){
			  printf("!!! Warning: Can not open file %s \n",OFName);
		      NumRun++;
		      fclose(fp);
		  }
		  else break;
	  }
  }
  printf("DAQ: Set the run number: %d \n\n\r", NumRun);
  /*---  Run note  ---*/
  printf("Note:");  
  fgets(OFName,200,stdin);
 
  unsigned int HitNumberADC0;
  unsigned int HitNumberADC1;

  unsigned int EVENT[BuffSize + 8];
  unsigned int ievent = 0;
  int iev;

  //event time 
  struct timeval tv;
  unsigned int sec;
  unsigned int microsec;
  time_t    timer;
  struct tm *date;

 /*---  write header  ---*/

  time(&timer);
  date = localtime(&timer);
  fprintf(fp,"*FORM = 04 marker=0xAABBCCDD\n");
  fprintf(fp,"*RUN = %d time %d:%d, date %d/%d/%d \n",RunNumber,date->tm_hour,date->tm_min,date->tm_mday,date->tm_mon+1,date->tm_year+1900);
  fprintf(fp,"*Calibration = %d, ",FLAG_CALIB);
  for(int im = 0; im < NumOfADC; im++){
    for(int ic = 0; ic < 2; ic++){ 
      fprintf(fp,"ADC %d = %d, ",ic + im*NumOfADC,ADC_Status[ic + im*NumOfADC]);
    }
  }
  fprintf(fp,"\n");
  
  fprintf(fp,"*init_SEQ: t1=%d, t2=%d, t3=%d, t4=%d, t5=%d \n",v551->time1,v551->time1,v551->time3,v551->time4,v551->time5);
  fprintf(fp,"*REM = %s",OFName);

  //taking data
  while(sig_int){
    
    while(!v551->GetBusy()) if(!sig_int) break;

    iev = 0;
    gettimeofday(&tv,NULL);
    sec = tv.tv_sec;
    microsec = tv.tv_usec;
    EVENT[iev++] = ievent;
    EVENT[iev++] = sec;
    EVENT[iev++] = microsec;
    EVENT[iev++] = 0;

    //waiting for data ready 
    while(!v551->GetDataRedy()) if(!sig_int) break;
    ievent++;
    if ( ievent -1 == atoi(NumEvents)) break;
    if ((ievent % 500) == 0) {
      printf("Event = %d \n\r",ievent);
      system("cat /dev/null >vmetrace.txt");
    }
    for(int i = 0; i < NumOfADC; i++){
    	v550[i]->GetWordCounter(HitNumberADC0,HitNumberADC1);
    	for(int ADC_int = 0; ADC_int < 2; ADC_int++){
    		if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
    		if(ADC_int == 0){
    			for(int chan = 0; chan < HitNumberADC0; chan++){
    				EVENT[iev++] = v550[i]->GetEvent(ADC_int);
    			}//chan
    		}//ADC0
    		if(ADC_int == 1){
    			for(int chan = 0; chan < HitNumberADC1; chan++){
    				EVENT[iev++] = v550[i]->GetEvent(ADC_int);
    			}//chan
    		}//ADC1
    		EVENT[iev++] = ((0xAABBCC00 | i << 1) | ADC_int); /*-- end of ADC --*/
    	}//ADC_int
    }//i
      
    EVENT[iev] = 0xAABBCCDD; /*-- end of event --*/
    fwrite(EVENT,4,iev + 1,fp);
  }//taking data
  
  fclose(fp);
  return 1;
}//Run
int RunDisplay(int RunNumber){

  v551->Init(NumOfChan);
  for(int i = 0; i < NumOfADC; i++) v550[i]->Init(NumOfChan);

  //Display variables
  FILE* displayFile = NULL; 
  int displayPointer = 0;

  char OFName[200];

  //Removing old display files
  sprintf(OFName,"./Display/display%d.dat",displayPointer);
  while(remove(OFName)==0){
    displayPointer++;
    sprintf(OFName,"./Display/display%d.dat",displayPointer);
  }

  displayPointer = 0;

  sprintf(OFName,"./DATA/si_run%d.dat",RunNumber);

  FILE* fp = fopen(OFName,"r");

  if(fp){

    printf("Do you want to rewrite file %s (y/n) \n\r",OFName);

    fgets(CharTmp,20,stdin);
    CharTmp[0] = toupper(CharTmp[0]);

    switch(CharTmp[0]){
      
    case 'Y':
      fclose(fp);
      fp = fopen(OFName,"w");
      break;
      
    case 'N':
      return 1;
      
    default:
      break; 
  
    }//switch
    
  }//if
  else{
    fp = fopen(OFName,"w");
    if(fp == NULL){
      printf("!!! Warning: Can not open file %s \n",OFName);
      return 1;
    }
  }

  /*---  Run note  ---*/
  printf("Note:");  
  fgets(OFName,200,stdin);
 
  unsigned int HitNumberADC0;
  unsigned int HitNumberADC1;

  unsigned int EVENT[BuffSize + 8];
  unsigned int ievent = 0;
  int iev;

  //event time 
  struct timeval tv;
  unsigned int sec;
  unsigned int microsec;
  time_t    timer;
  struct tm *date;

 /*---  write header  ---*/

  time(&timer);
  date = localtime(&timer);
  fprintf(fp,"*FORM = 04 marker=0xAABBCCDD\n");
  fprintf(fp,"*RUN = %d time %d:%d, date %d/%d/%d \n",RunNumber,date->tm_hour,date->tm_min,date->tm_mday,date->tm_mon+1,date->tm_year+1900);
  fprintf(fp,"*Calibration = %d, ",FLAG_CALIB);
  for(int im = 0; im < NumOfADC; im++){
    for(int ic = 0; ic < 2; ic++){ 
      fprintf(fp,"ADC %d = %d, ",ic + im*NumOfADC,ADC_Status[ic + im*NumOfADC]);
    }
  }
  fprintf(fp,"\n");
  
  fprintf(fp,"*init_SEQ: t1=%d, t2=%d, t3=%d, t4=%d, t5=%d \n",v551->time1,v551->time1,v551->time3,v551->time4,v551->time5);
  fprintf(fp,"*REM = %s",OFName);

  //taking data
  while(sig_int){
    
    if(!(ievent%10)){

      if(displayFile) fclose(displayFile);
      sprintf(OFName,"./Display/display%d.dat",displayPointer);
      displayFile = fopen(OFName,"w");
      displayPointer++;

    }

    while(!v551->GetBusy()) if(!sig_int) break;

    iev = 0;
    gettimeofday(&tv,NULL);
    sec = tv.tv_sec;
    microsec = tv.tv_usec;
    EVENT[iev++] = ievent;
    EVENT[iev++] = sec;
    EVENT[iev++] = microsec;
    EVENT[iev++] = 0;

    //waiting for data ready 
    while(!v551->GetDataRedy()) if(!sig_int) break;
 
    ievent++;
    
    printf("Event = %d \n\r",ievent);

    for(int i = 0; i < NumOfADC; i++){
      
      v550[i]->GetWordCounter(HitNumberADC0,HitNumberADC1);

      for(int ADC_int = 0; ADC_int < 2; ADC_int++){
	
	if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
	
	if(ADC_int == 0){
	  
	  for(int chan = 0; chan < HitNumberADC0; chan++){
	    
	    EVENT[iev++] = v550[i]->GetEvent(ADC_int);

	  }//chan
	  
	}//ADC0
	
	if(ADC_int == 1){
	  
	  for(int chan = 0; chan < HitNumberADC1; chan++){
	    
	    EVENT[iev++] = v550[i]->GetEvent(ADC_int);
   
	  }//chan
	  
	}//ADC1
	
	EVENT[iev++] = ((0xAABBCC00 | i << 1) | ADC_int); /*-- end of ADC --*/
	
      }//ADC_int
      
    }//i
      
    EVENT[iev] = 0xAABBCCDD; /*-- end of event --*/
    fwrite(EVENT,4,iev + 1,fp);
    if(displayFile) fwrite(EVENT,4,iev + 1,displayFile);

  }//taking data
  
  fclose(fp);
  if(displayFile) fclose(displayFile);

  return 1;

}//RunDisplay
void CalibAutoTrig(){

  unsigned int HitNumberADC0;
  unsigned int HitNumberADC1;
  unsigned int OR;
  unsigned int V;
  int ChNum;
  int ChData;
  int SilcPointer;

  v551->Init(NumOfChan);

  for(int i = 0; i < NumOfADC; i++){
    v550[i]->Init(NumOfChan);
    v550[i]->SetPedThrZero();
  }//i
  
  int* Ped = new int[BuffSize];
  int* Ped2 = new int[BuffSize];
  int* Noi = new int[BuffSize];
  int* Norm = new int[BuffSize];

  for(int tmp = 0; tmp < BuffSize; tmp++){
    
    Ped[tmp] = 0;
    Ped2[tmp] = 0;
    Noi[tmp] = 0;
    Norm[tmp] = 0;
  
  }//tmp

  for(int i_trig = 0; i_trig < 1000; i_trig++){
    v551->SoftwareTrigger();
    if((i_trig%100) == 0) printf("Calibration: Event - %d \n\r",i_trig);
    SilcPointer = 0;
    for(int i = 0; i < NumOfADC; i++){
      while(!v551->GetDataRedy());
      v550[i]->GetWordCounter(HitNumberADC0,HitNumberADC1);
       for(int ADC_int = 0; ADC_int < 2; ADC_int++){
	if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
	if(ADC_int == 0){
	  for(int chan = 0; chan < HitNumberADC0; chan++){
	    v550[i]->GetFifo0(OR,V,&ChNum,&ChData);
	    Ped[ChNum + SilcPointer*NumOfChan] += ChData;
	    Ped2[ChNum + SilcPointer*NumOfChan] += ChData*ChData;
	    Norm[ChNum + SilcPointer*NumOfChan] += 1;	    
	  }//chan
	  SilcPointer++;
	}//ADC0
	if(ADC_int == 1){
	  for(int chan = 0; chan < HitNumberADC1; chan++){
	    v550[i]->GetFifo1(OR,V,&ChNum,&ChData);
	    Ped[ChNum + SilcPointer*NumOfChan] += ChData;
	    Ped2[ChNum + SilcPointer*NumOfChan] += ChData*ChData;
	    Norm[ChNum + SilcPointer*NumOfChan] += 1;	    
	  }//chan
	  SilcPointer++;
	}//ADC1
      }//ADC_int
    }//i
  }//i_trig
  for(int tmp = 0; tmp < BuffSize; tmp++){
    if(Norm[tmp] > 1){
      Ped[tmp] = Ped[tmp]/Norm[tmp];
      Ped2[tmp] = Ped2[tmp]/Norm[tmp];
      Noi[tmp] = (int)(sqrt((Norm[tmp]/(Norm[tmp] - 1))*(Ped2[tmp] - Ped[tmp]*Ped[tmp])));
    }
    else{
      Ped[tmp] = 0;
      Noi[tmp] = 0;
    }

  }//tmp
  
  int ped_tmp, thr_tmp;
  SilcPointer = 0;
  for(int i = 0; i < NumOfADC; i++){
    for(int ADC_int = 0; ADC_int < 2; ADC_int++){
      if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
      for(int chan = 0; chan < NumOfChan; chan++){
    	  ped_tmp = Ped[chan + SilcPointer*NumOfChan];
    	  thr_tmp = ped_tmp + 3*Noi[chan + SilcPointer*NumOfChan];
    	  v550[i]->SetPedestalThreshold(ADC_int,chan,ped_tmp,thr_tmp);
      }//chan
      SilcPointer++;
    }//ADC_int
  }//i
  
  ped_tmp = 0;
  thr_tmp = 0;

  int PedMax = 700;
  int NoiMax = 100;

  unsigned int hPed[NumOfChan];
  unsigned int hThr[NumOfChan];
  unsigned int hPedestal[PedMax];
  unsigned int hNoise[NoiMax];

  SilcPointer = 0;

  for(int i = 0; i < NumOfADC; i++){
    for(int ADC_int = 0; ADC_int < 2; ADC_int++){
      mreset(hPed,NumOfChan);
      mreset(hThr,NumOfChan);
      mreset(hPedestal,PedMax);
      mreset(hNoise,NoiMax);
      if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
      for(int chan = 0; chan < NumOfChan; chan++){
    	  v550[i]->GetPedestalThreshold(ADC_int,chan,&ped_tmp,&thr_tmp);
    	  mfill(hPed,NumOfChan,chan,ped_tmp);
    	  mfill(hThr,NumOfChan,chan,thr_tmp);
    	  mfill(hPedestal,PedMax,Ped[chan + SilcPointer*NumOfChan],1);
    	  mfill(hNoise,NoiMax,Noi[chan + SilcPointer*NumOfChan],1);
      }//chan
      SilcPointer++;
      printf("------------------------------------------------- PLANE %d -------------------------------------------------\n\r",SilcPointer);
      hprint(hPed,NumOfChan,"Pedestals vs chan ");
      hprint(hThr,NumOfChan,"Threshold vs chan ");
      hprint(hPedestal,PedMax,"Pedestals distribution ");
      hprint(hNoise,NoiMax,"Noise distribution ");
      printf("-------------------------------------------------------------------------------------------------------------\n\r");
    }//ADC_int
  }//i
  
  FLAG_CALIB = 2;

  delete [] Ped;
  delete [] Ped2;
  delete [] Noi;
  delete [] Norm;
  
  WriteCalFile();

}//CalibAutoTrig
void CalibExtTrig(){

  unsigned int HitNumberADC0;
  unsigned int HitNumberADC1;
  unsigned int OR;
  unsigned int V;
  int ChNum;
  int ChData;
  int SilcPointer;

  v551->Init(NumOfChan);

  for(int i = 0; i < NumOfADC; i++){
    v550[i]->Init(NumOfChan);
    v550[i]->SetPedThrZero();
  }//i
  
  int* Ped = new int[BuffSize];
  int* Ped2 = new int[BuffSize];
  int* Noi = new int[BuffSize];
  int* Norm = new int[BuffSize];

  for(int tmp = 0; tmp < BuffSize; tmp++){
    Ped[tmp] = 0;
    Ped2[tmp] = 0;
    Noi[tmp] = 0;
    Norm[tmp] = 0;
  }//tmp

  for(int i_trig = 0; i_trig < 1000; i_trig++){
    if((i_trig%100) == 0) printf("Calibration: Event - %d \n\r",i_trig);
    SilcPointer = 0;
    for(int i = 0; i < NumOfADC; i++){
      while(!v551->GetDataRedy());
      v550[i]->GetWordCounter(HitNumberADC0,HitNumberADC1);
      for(int ADC_int = 0; ADC_int < 2; ADC_int++){
	if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
	if(ADC_int == 0){
	  for(int chan = 0; chan < HitNumberADC0; chan++){
	    v550[i]->GetFifo0(OR,V,&ChNum,&ChData);
	    Ped[ChNum + SilcPointer*NumOfChan] += ChData;
	    Ped2[ChNum + SilcPointer*NumOfChan] += ChData*ChData;
	    Norm[ChNum + SilcPointer*NumOfChan] += 1;	    
	  }//chan
	  SilcPointer++;
	}//ADC0
	if(ADC_int == 1){
	  for(int chan = 0; chan < HitNumberADC1; chan++){
	    v550[i]->GetFifo1(OR,V,&ChNum,&ChData);
	    Ped[ChNum + SilcPointer*NumOfChan] += ChData;
	    Ped2[ChNum + SilcPointer*NumOfChan] += ChData*ChData;
	    Norm[ChNum + SilcPointer*NumOfChan] += 1;	    
	  }//chan
	  SilcPointer++;
	}//ADC1
      }//ADC_int
    }//i
  }//i_trig
  for(int tmp = 0; tmp < BuffSize; tmp++){
    if(Norm[tmp] > 1){
      Ped[tmp] = Ped[tmp]/Norm[tmp];
      Ped2[tmp] = Ped2[tmp]/Norm[tmp];
      Noi[tmp] = (int)(sqrt((Norm[tmp]/(Norm[tmp] - 1))*(Ped2[tmp] - Ped[tmp]*Ped[tmp])));
    }
    else{
      Ped[tmp] = 0;
      Noi[tmp] = 0;
    }
  }//tmp
  int ped_tmp, thr_tmp;
  SilcPointer = 0;
  for(int i = 0; i < NumOfADC; i++){
    for(int ADC_int = 0; ADC_int < 2; ADC_int++){
      if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
      for(int chan = 0; chan < NumOfChan; chan++){
	ped_tmp = Ped[chan + SilcPointer*NumOfChan];
	thr_tmp = ped_tmp + 3*Noi[chan + SilcPointer*NumOfChan];
	v550[i]->SetPedestalThreshold(ADC_int,chan,ped_tmp,thr_tmp);
      }//chan
      SilcPointer++;
      
    }//ADC_int
  }//i
  
  ped_tmp = 0;
  thr_tmp = 0;

  int PedMax = 700;
  int NoiMax = 100;

  unsigned int hPed[NumOfChan];
  unsigned int hThr[NumOfChan];
  unsigned int hPedestal[PedMax];
  unsigned int hNoise[NoiMax];

  SilcPointer = 0;

  for(int i = 0; i < NumOfADC; i++){
    for(int ADC_int = 0; ADC_int < 2; ADC_int++){
      
      mreset(hPed,NumOfChan);
      mreset(hThr,NumOfChan);
      mreset(hPedestal,PedMax);
      mreset(hNoise,NoiMax);
      
      if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
      
      for(int chan = 0; chan < NumOfChan; chan++){
	v550[i]->GetPedestalThreshold(ADC_int,chan,&ped_tmp,&thr_tmp);
	mfill(hPed,NumOfChan,chan,ped_tmp);
	mfill(hThr,NumOfChan,chan,thr_tmp);
	mfill(hPedestal,PedMax,Ped[chan + SilcPointer*NumOfChan],1);
	mfill(hNoise,NoiMax,Noi[chan + SilcPointer*NumOfChan],1);
      }//chan
      SilcPointer++;

      printf("------------------------------------------------- PLANE %d -------------------------------------------------\n\r",SilcPointer);
      hprint(hPed,NumOfChan,"Pedestals vs chan ");
      hprint(hThr,NumOfChan,"Threshold vs chan ");
      hprint(hPedestal,PedMax,"Pedestals distribution ");
      hprint(hNoise,NoiMax,"Noise distribution ");
      printf("-------------------------------------------------------------------------------------------------------------\n\r");
      
    }//ADC_int
  }//i

  FLAG_CALIB = 1;
  
  delete [] Ped;
  delete [] Ped2;
  delete [] Noi;
  delete [] Norm;

  WriteCalFile();

}//CalibExtTrig
void SetZero(){

  for(int i = 0; i < NumOfADC; i++) v550[i]->SetPedThrZero();

  printf("============================================================================ \n\n\r");
  printf("!!! Warning: Right now all pedestals and thresholds are set to zero           \n\r");
  printf("!!! Warning: Before taking data you have to make calibration                  \n\r");
  printf("!!! Warning: Close the shutter and use calibration in the auto trigger mode \n\n\r");
  printf("============================================================================ \n\n\r");

  FLAG_CALIB = 1;

}//SetZero
void ReadCalFile(){
	int ped_tmp, thr_tmp;
	int tmp;
	int NumOfCrate;
	int ADC_int;
	FILE* SiFile;
	char OFName[200];
	double 	Trigger[2];

    printf("DAQ: Set the calibration number: ");
    fgets(CharTmp,20,stdin);

	sprintf(OFName,"./DATA/Calibration_%d.dat", atoi(CharTmp) );
	SiFile = fopen(OFName,"r");

	if(!SiFile){
		printf("!!! ERROR !!!");
		printf("File does not exist");
		return ;
	}
    //Run Header
    char Header[80];
    for(int i = 0; i < 4; i++){
      fgets(Header,80,SiFile); printf("%s",Header);
    }
    int chan = 0;
    NumOfCrate = 0;
    ADC_int=0;
	for(int i = 0; i < EventLength; i++){//For all channel of strip detector  //EventLength
		if(feof(SiFile) || ferror(SiFile)) return ;
	    fread(&tmp,4,1,SiFile);

	    chan++;

	    //printf("TMP0=%x \n", tmp);
	    if(tmp == 0xAABBCCDD)  break;
	    //end of first telescope
	    if(tmp == 0xAABBCC00){ NumOfCrate = 0; ADC_int = 0; chan = 0;  continue; 	}
	    //end of second telescope
	    if(tmp == 0xAABBCC01){ NumOfCrate = 0; ADC_int = 1; chan = 0;  continue;  }
	    //end of second telescope
	    if(tmp == 0xAABBCC03){ NumOfCrate = 1; ADC_int = 0; chan = 0;  continue;	}

	    if(!ADC_Status[ADC_int + NumOfCrate*NumOfADC]) continue;

	    v550[NumOfCrate]->SetPedestalThresholdFull(ADC_int, chan, tmp);

	  }//for
	  //fclose(SiFile);

	  if(feof(SiFile) || ferror(SiFile)) {
		  return ;
	  }
	  return ;
}
void WriteCalFile(){
	char OFName[200];
	int SilcPointer;
	int iev;
	unsigned int CalVal[BuffSize + 8];

	FILE* fp ;
	//========================
	//
	//========================
	while(1){
	  sprintf(OFName,"./DATA/Calibration_%d.dat",CalRunNum);
	  fp = fopen(OFName,"r");
	  if(fp){
		  CalRunNum++;
		  fclose(fp);
	  }//if
	  else{
		  fp = fopen(OFName,"w");
		  if(fp == NULL){
			  printf("!!! Warning: Can not open file %s \n",OFName);
			  CalRunNum++;
		      fclose(fp);
		  }
		  else break;
	  }
	 }
	 printf("DAQ: You calibration file is: %d \n\n\r", CalRunNum);
	 /*---  Run note  ---*/
	 printf("Note for calibration file:");
	 fgets(OFName,200,stdin);

	 //event time
	 struct timeval tv;
	 unsigned int sec;
	 unsigned int microsec;
	 time_t    timer;
	 struct tm *date;

	 /*---  write header  ---*/

	 time(&timer);
	 date = localtime(&timer);
	 fprintf(fp,"*Calibration file: %d \n", CalRunNum);
	 fprintf(fp,"*time %d:%d, date %d/%d/%d \n",date->tm_hour, date->tm_min, date->tm_mday, date->tm_mon+1, date->tm_year+1900);
	 fprintf(fp,"*init_SEQ: t1=%d, t2=%d, t3=%d, t4=%d, t5=%d \n",v551->time1,v551->time1,v551->time3,v551->time4,v551->time5);
	 fprintf(fp,"*REM = %s",OFName);

	 int ped_tmp, thr_tmp, PedThr;
	 int chan;

	 ped_tmp = 0;
	 thr_tmp = 0;

	 int PedMax = 700;
	 int NoiMax = 100;

	 unsigned int hPed[NumOfChan];
	 unsigned int hThr[NumOfChan];
	 unsigned int hPedestal[PedMax];

     iev = 0;
     CalVal[iev] = 0xAABBCC00;
	 for(int i = 0; i < NumOfADC; i++){//number of crate
		 for(int ADC_int = 0; ADC_int < 2; ADC_int++){//number of ADC
			 if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
			 CalVal[iev++] = ( (0xAABBCC00 | i << 1) | ADC_int); /*-- end of ADC --*/
			 for(int chan = 0; chan < NumOfChan; chan++){
				 //v550[i]->GetPedestalThreshold(ADC_int,chan,&ped_tmp,&thr_tmp);
				 v550[i]->GetPedestalThresholdFull(ADC_int, chan, &PedThr);
				 CalVal[iev++] = PedThr;
				 //printf("Crate=%d, ADC=%d, ch= %d PED=%d, THR=%d\n\r", i, ADC_int, chan, ped_tmp, thr_tmp );
			 }//chan
		 }//ADC_int
	 }//i
	 CalVal[iev++] = 0xAABBCCDD; /*-- end of Pedistal Threshold --*/
	 fwrite(CalVal,4,iev + 1,fp);
	 fclose(fp);
}
